package com.park.jwt;

import cn.hutool.core.date.DateField;
import cn.hutool.core.date.DateTime;
import cn.hutool.core.date.DateUnit;
import cn.hutool.core.date.DateUtil;
import com.auth0.jwt.JWT;
import com.auth0.jwt.JWTVerifier;
import com.auth0.jwt.algorithms.Algorithm;
import com.auth0.jwt.exceptions.JWTCreationException;
import com.auth0.jwt.exceptions.JWTVerificationException;
import com.auth0.jwt.interfaces.Claim;
import com.auth0.jwt.interfaces.DecodedJWT;
import com.park.comm.ResultEnum;
import com.park.exception.CommException;

import java.util.Date;
import java.util.HashMap;
import java.util.Map;

/**
 * @author Administrator
 * @title: TokenUtils
 * @projectName park
 * @description: Token生成工具
 * @date 2020/5/517:36
 */
public class TokenUtils {

    private static final String secretCode = "5d2c4c5ce1d46552cbb80a13eb434e2a";

    /* *
     * @Author zhanghaiwen
     * @Description 生成用户登录的Token
     * @Date 21:50 2019/4/11
     * @Param []
     * @return java.lang.String
     */
    public static String createTokenWithClaim(Integer userId) {
        DateTime date = DateUtil.date();
        try {
            Algorithm algorithm = Algorithm.HMAC256(secretCode);
            Map<String, Object> map = new HashMap<String, Object>();
            Date expireDate = DateUtil.offsetDay(DateUtil.date(), 15);
            map.put("alg", "HS256");
            map.put("typ", "JWT");
            String token = JWT.create()
                    /*设置头部信息 Header*/
                    .withHeader(map)
                    /*设置 载荷 Payload*/
                    .withIssuer("SERVICE")//签名是有谁生成 例如 服务器
                    .withSubject(String.valueOf(userId))//代表这个JWT的主体，即它的所有人，这个是一个json格式的字符串，可以存放什么userid，roldid之类的，作为什么用户的唯一标志。
                    //.withNotBefore(new Date())//定义在什么时间之前，该jwt都是不可用的.
                    //.withAudience(equipment)//签名的观众 也可以理解谁接受签名的
                    .withIssuedAt(date) //生成签名的时间
                    .withExpiresAt(expireDate)//签名过期的时间
                    //.withJWTId("asd") //是JWT的唯一标识，根据业务需要，这个可以设置为一个不重复的值，主要用来作为一次性token,从而回避重放攻击。
                    /*签名 Signature */
                    .sign(algorithm); //设置签名使用的签名算法和签名使用的秘钥
            return token;
        } catch (JWTCreationException exception){
            exception.printStackTrace();
        }
        return null;
    }

    /* *
     * @Author zhanghaiwen
     * @Description 解析Token 用户登录
     * @Date 21:50 2019/4/11
     * @Param [token]
     * @return void
     */
    public static Map<String,String> verifyToken(String token) {
        try {
            Algorithm algorithm = Algorithm.HMAC256(secretCode);
            JWTVerifier verifier = JWT.require(algorithm)
                    .withIssuer("SERVICE")
                    .build();
            DecodedJWT jwt = verifier.verify(token);
            String userId = jwt.getSubject();
            Map<String, Claim> claims = jwt.getClaims();
            Map userLoginMap = new HashMap();
            userLoginMap.put("userId",userId);
            return userLoginMap;
        } catch (JWTVerificationException exception){
            throw new CommException(ResultEnum.APP_USER_OVER_TIME_LOGIN);
        }
    }


}
